#ifndef MSGPOOL_INC
#define MSGPOOL_INC

#include "Common/Singleton.h"
#include "Common/Queue.h"
#include "Common/Stream.h"
#include "MsgHandler/MsgTypes.h"
#include "wch/Mutex.h"

class MsgPool
	: public Singleton<MsgPool>
{
protected:
	MsgPool() {};
	virtual ~MsgPool() {}
	friend class Singleton<MsgPool>;

public:
	bool init(UInt8);
	void unInit();

public:
	template <typename MsgHdrType>
	inline void pushMsg( const MsgHdrType& hdr, void * msgBody )
	{
		UInt8 workerId = hdr._loc;
		if ( workerId > _workerCount || workerId <= 0 )
			return;
		char * buffer = new(std::nothrow) char[sizeof(MsgHdrType) + hdr._len];
		ASSERT( buffer != nullptr );
		memcpy(buffer, &hdr, sizeof(MsgHdrType));
		if ( msgBody != nullptr && hdr._len > 0 )
			memcpy( buffer + sizeof( MsgHdrType ), msgBody, hdr._len );
		wch::FastMutex::ScopedLock lock(m_MsgMutex[workerId-1]);
		m_MsgQueue[workerId-1].Push((MsgHdr*)buffer);
	}

	inline void pushMsg( UInt8 workerId, Stream& st )
	{
		ASSERT( workerId >= 1 && workerId <= _workerCount );
		char * buffer = new(std::nothrow) char[st.size()];
		ASSERT( buffer != nullptr );
		memcpy( buffer, &st[0], st.size() );
		wch::FastMutex::ScopedLock lock( m_MsgMutex[workerId-1] );
		m_MsgQueue[workerId-1].Push( (MsgHdr*)buffer );
	}

	inline bool getMsgQueue( UInt8 workerId, MsgQueue& popMsgQueue )
	{
		ASSERT( workerId >= 1 && workerId <= _workerCount );
		wch::FastMutex::ScopedLock lock(m_MsgMutex[workerId-1]);
		if(m_MsgQueue[workerId-1].Empty())
			return false;
		popMsgQueue = m_MsgQueue[workerId-1];
		m_MsgQueue[workerId-1].Clear();
		return true;
	}

private:
	UInt8	_workerCount;
	MsgQueue *			m_MsgQueue;
	wch::FastMutex *	m_MsgMutex;
};

#define MSGPOOL()	MsgPool::Instance()

#endif